#include "px_rendersystem.h"
#include "../utility/px_system.h"
#include "../utility/px_macros.h"
#include "GL/glew.h"
#include "../kazmath/kazmath.h"
#include "../kazmath/GL/matrix.h"
static PXVIEW *s_pView = NULL;
#define  kWindowClassName  TEXT("Cocos2dxWin32")
PXVIEW * share_PXVIEW()
{
	if(s_pView == NULL)
	{
		s_pView = (PXVIEW *) malloc(sizeof(PXVIEW));
	}
	return s_pView;
}
static void _setup_pixelFormat(HDC hDC)
{
	int pixelFormat;

	PIXELFORMATDESCRIPTOR pfd =
	{   
		sizeof(PIXELFORMATDESCRIPTOR),  // size
		1,                          // version
		PFD_SUPPORT_OPENGL |        // OpenGL window
		PFD_DRAW_TO_WINDOW |        // render to window
		PFD_DOUBLEBUFFER,           // support double-buffering
		PFD_TYPE_RGBA,              // color type
		32,                         // prefered color depth
		0, 0, 0, 0, 0, 0,           // color bits (ignored)
		0,                          // no alpha buffer
		0,                          // alpha bits (ignored)
		0,                          // no accumulation buffer
		0, 0, 0, 0,                 // accum bits (ignored)
		16,                         // depth buffer
		0,                          // no stencil buffer
		0,                          // no auxiliary buffers
		PFD_MAIN_PLANE,             // main layer
		0,                          // reserved
		0, 0, 0,                    // no layer, visible, damage masks
	};

	pixelFormat = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, pixelFormat, &pfd);
}
PXBOOL init_GL(PXVIEW * pView)
{
	pView->hDC = GetDC(pView->hwind);
     _setup_pixelFormat(pView->hDC);
	//SetupPalette();
	pView->hRC = wglCreateContext(pView->hDC);
	wglMakeCurrent(pView->hDC, pView->hRC);
	GLenum GlewInitResult = glewInit();
	if (GLEW_OK != GlewInitResult) 
	{
	//	fprintf(stderr,"ERROR: %s\n",glewGetErrorString(GlewInitResult));
		return false;
	}

	if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
	{
		//Ready for GLSL
	}
	else 
	{
		//Not totally ready :( \n
	}

	if (glewIsSupported("GL_VERSION_2_0"))
	{
		//Ready for OpenGL 2.0
	}
	else
	{
		//OpenGL 2.0 not supported;
	}
	return PXTURE;
}
void destroy_GL(PXVIEW * pView)
{
	if (pView->hDC != NULL && pView->hRC != NULL)
	{
		// deselect rendering context and delete it
		wglMakeCurrent(pView->hDC, NULL);
		wglDeleteContext(pView->hRC);
	}
}

void center_window( PXVIEW * pView )
{
	RECT rcDesktop, rcWindow;
	HWND hTaskBar;
	int offsetX,offsetY;
	if (! pView->hwind)
	{
		return;
	}
	GetWindowRect(GetDesktopWindow(), &rcDesktop);
	// substract the task bar
	 hTaskBar = FindWindow(TEXT("Shell_TrayWnd"), NULL);
	if (hTaskBar != NULL)
	{
		APPBARDATA abd;

		abd.cbSize = sizeof(APPBARDATA);
		abd.hWnd = hTaskBar;

		SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
		SubtractRect(&rcDesktop, &rcDesktop, &abd.rc);
	}
	GetWindowRect(pView->hwind, &rcWindow);

	offsetX = (rcDesktop.right - rcDesktop.left - (rcWindow.right - rcWindow.left)) / 2;
	offsetX = (offsetX > 0) ? offsetX : rcDesktop.left;
	offsetY = (rcDesktop.bottom - rcDesktop.top - (rcWindow.bottom - rcWindow.top)) / 2;
	offsetY = (offsetY > 0) ? offsetY : rcDesktop.top;

	SetWindowPos(pView->hwind, 0, offsetX, offsetY, 0, 0, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}

void resize_window( PXVIEW * pView ,int width, int height )
{
	RECT rcClient;
	if (! pView->hwind)
	{
		return;
	}	
	GetClientRect(pView->hwind, &rcClient);
	if (rcClient.right - rcClient.left == width &&
		rcClient.bottom - rcClient.top == height)
	{
		return;
	}
	// calculate new window width and height
	rcClient.right = rcClient.left + width;
	rcClient.bottom = rcClient.top + height;
	AdjustWindowRectEx(&rcClient, GetWindowLong(pView->hwind, GWL_STYLE), false, GetWindowLong(pView->hwind, GWL_EXSTYLE));
	// change width and height
	SetWindowPos(pView->hwind, 0, 0, 0, rcClient.right - rcClient.left, 
		rcClient.bottom - rcClient.top, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}

LRESULT _window_proc(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_LBUTTONDOWN:
	
		break;

	case WM_MOUSEMOVE:
		break;

	case WM_LBUTTONUP:
		break;
	case WM_KEYDOWN:

		break;
	case WM_KEYUP:
	
		break;
	case WM_CHAR:
		break;
	case WM_PAINT:
		PAINTSTRUCT ps;
		BeginPaint(s_pView->hwind, &ps);
		EndPaint(s_pView->hwind, &ps);
		break;
	case WM_CLOSE:
		break;
	case WM_DESTROY:
		destroy_GL(s_pView);
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(s_pView->hwind, message, wParam, lParam);
	}
	return 0;
}
static LRESULT CALLBACK _WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (s_pView && s_pView->hwind == hWnd)
	{
		return _window_proc(uMsg, wParam, lParam);
	}
	else
	{
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
}
PXBOOL create_window(PXVIEW * pView ,LPCTSTR pTitle, int w, int h)
{
	bool bRet = false;
	do 
	{
		WCHAR wszBuf[50] = {0};
		HINSTANCE hInstance;
		WNDCLASS  wc;        // Windows Class Structure
		PX_BREAK_IF(pView->hwind);
		hInstance = GetModuleHandle( NULL );

		// Redraw On Size, And Own DC For Window.
		wc.style          = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  
		wc.lpfnWndProc    = _WindowProc;                    // WndProc Handles Messages
		wc.cbClsExtra     = 0;                              // No Extra Window Data
		wc.cbWndExtra     = 0;                                // No Extra Window Data
		wc.hInstance      = hInstance;                        // Set The Instance
		wc.hIcon          = LoadIcon( NULL, IDI_WINLOGO );    // Load The Default Icon
		wc.hCursor        = LoadCursor( NULL, IDC_ARROW );    // Load The Arrow Pointer
		wc.hbrBackground  = NULL;                           // No Background Required For GL
		wc.lpszMenuName   = NULL;                           // We Don't Want A Menu
		wc.lpszClassName  = kWindowClassName;               // Set The Class Name

		PX_BREAK_IF(! RegisterClass(&wc) && 1410 != GetLastError());        

		// center window position
		RECT rcDesktop;
		GetWindowRect(GetDesktopWindow(), &rcDesktop);

// 		WCHAR wszBuf[50] = {0};
// 		MultiByteToWideChar(CP_UTF8, 0, pTitle, -1, wszBuf, sizeof(wszBuf));

		// create window
		pView->hwind = CreateWindowEx(
			WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,    // Extended Style For The Window
			kWindowClassName,                                    // Class Name
			pTitle,                                                // Window Title
			WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX,        // Defined Window Style
			0, 0,                                                // Window Position
			0,                                                  // Window Width
			0,                                                  // Window Height
			NULL,                                                // No Parent Window
			NULL,                                                // No Menu
			hInstance,                                            // Instance
			NULL );

		PX_BREAK_IF(!pView->hwind);
		resize_window(pView,w, h);
		bRet = init_GL(pView);
		PX_BREAK_IF(!bRet);
		bRet = true;
	} while (0);

	return bRet;
}

void swap_buffer(PXVIEW * pView)
{
	::SwapBuffers(pView->hDC);
}

void set_projection( PXVIEW * pView )
{

	float zeye = SCREEN_HEIGHT/ 1.1566f;

	kmMat4 matrixPerspective, matrixLookup;
	kmVec3 eye, center, up;

	glViewport(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
	kmGLMatrixMode(KM_GL_PROJECTION);
	kmGLLoadIdentity();
	glTranslatef(-1.0f,-1.0f,0.0f);
	// issue #1334
	kmMat4PerspectiveProjection( &matrixPerspective, 60, (GLfloat)SCREEN_WIDTH/SCREEN_HEIGHT, 0.1f, zeye*2);
	// kmMat4PerspectiveProjection( &matrixPerspective, 60, (GLfloat)size.width/size.height, 0.1f, 1500);

	kmGLMultMatrix(&matrixPerspective);

	kmGLMatrixMode(KM_GL_MODELVIEW);
	kmGLLoadIdentity();

	kmVec3Fill( &eye, SCREEN_WIDTH/2, SCREEN_HEIGHT/2, zeye );
	kmVec3Fill( &center, SCREEN_WIDTH/2, SCREEN_HEIGHT/2, 0.0f );
	kmVec3Fill( &up, 0.0f, 1.0f, 0.0f);
	kmMat4LookAt(&matrixLookup, &eye, &center, &up);
	kmGLMultMatrix(&matrixLookup);

	glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glHint(GL_LINE_SMOOTH_HINT,GL_DONT_CARE);
	
}
